// cmd/vmctl/commands/output.go
package commands

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"text/tabwriter"

	"gopkg.in/yaml.v3"
	"virt-manager-go/internal/domain"
)

// OutputFormat 定义支持的输出格式
type OutputFormat string

const (
	FormatTable OutputFormat = "table"
	FormatJSON  OutputFormat = "json"
	FormatYAML  OutputFormat = "yaml"
)

// GetOutputFormat 从命令行标志获取输出格式
func GetOutputFormat(format string) OutputFormat {
	switch strings.ToLower(format) {
	case "json":
		return FormatJSON
	case "yaml":
		return FormatYAML
	default:
		return FormatTable
	}
}

// OutputFormatter 输出格式化器接口
type OutputFormatter interface {
	FormatVMList(vms []domain.VMInfo) error
	FormatVMInfo(vm *domain.VMInfo) error
	FormatStoragePoolList(pools []domain.StoragePoolInfo) error
	FormatStorageVolumeList(volumes []domain.StorageVolumeInfo) error
	FormatSnapshotList(snapshots []domain.SnapshotInfo) error
	FormatNetworkList(networks []domain.NetworkInfo) error
	FormatConnectionList(connections []domain.ConnectionInfo) error
	FormatDHCPLeases(leases []domain.DHCPLease) error
	FormatEventList(events []domain.Event) error
}

// TableFormatter 表格格式输出
type TableFormatter struct{}

func (f *TableFormatter) FormatVMList(vms []domain.VMInfo) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "NAME\tSTATE\tCPUs\tMEMORY\tAUTOSTART\tUUID")
	fmt.Fprintln(w, "----\t-----\t----\t------\t---------\t----")

	for _, vm := range vms {
		autostart := "no"
		if vm.Autostart {
			autostart = "yes"
		}
		fmt.Fprintf(w, "%s\t%s\t%d\t%d MB\t%s\t%s\n",
			vm.Name,
			vm.State,
			vm.CPUs,
			vm.Memory/1024,
			autostart,
			vm.UUID[:8])
	}
	return w.Flush()
}

func (f *TableFormatter) FormatVMInfo(vm *domain.VMInfo) error {
	fmt.Printf("VM: %s\n", vm.Name)
	fmt.Printf("  UUID:        %s\n", vm.UUID)
	fmt.Printf("  State:       %s\n", vm.State)
	fmt.Printf("  CPUs:        %d\n", vm.CPUs)
	fmt.Printf("  Memory:      %d MB\n", vm.Memory/1024)
	fmt.Printf("  Max Memory:  %d MB\n", vm.MaxMemory/1024)
	fmt.Printf("  Autostart:   %v\n", vm.Autostart)
	fmt.Printf("  Persistent:  %v\n", vm.Persistent)

	if len(vm.Disks) > 0 {
		fmt.Println("  Disks:")
		for _, disk := range vm.Disks {
			fmt.Printf("    - %s (%s, %s)\n", disk.Target, disk.Bus, disk.Format)
		}
	}

	if len(vm.Networks) > 0 {
		fmt.Println("  Networks:")
		for _, net := range vm.Networks {
			fmt.Printf("    - %s (%s)\n", net.Name, net.Domain)
		}
	}
	return nil
}

func (f *TableFormatter) FormatStoragePoolList(pools []domain.StoragePoolInfo) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "NAME\tSTATE\tCAPACITY\tALLOCATION\tAVAILABLE\tVOLUMES")
	fmt.Fprintln(w, "----\t-----\t--------\t----------\t---------\t-------")

	for _, pool := range pools {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%d\n",
			pool.Name,
			pool.State,
			formatBytes(pool.Capacity),
			formatBytes(pool.Allocation),
			formatBytes(pool.Available),
			pool.Volumes)
	}
	return w.Flush()
}

func (f *TableFormatter) FormatStorageVolumeList(volumes []domain.StorageVolumeInfo) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "NAME\tFORMAT\tCAPACITY\tALLOCATION\tPATH")
	fmt.Fprintln(w, "----\t------\t--------\t----------\t----")

	for _, vol := range volumes {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
			vol.Name,
			vol.Format,
			formatBytes(vol.Capacity),
			formatBytes(vol.Allocation),
			vol.Path)
	}
	return w.Flush()
}

func (f *TableFormatter) FormatSnapshotList(snapshots []domain.SnapshotInfo) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "NAME\tCURRENT\tSTATE\tCREATED\tDESCRIPTION")
	fmt.Fprintln(w, "----\t-------\t-----\t-------\t-----------")

	for _, snap := range snapshots {
		current := ""
		if snap.IsCurrent {
			current = "*"
		}
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
			snap.Name,
			current,
			snap.State,
			snap.CreatedAt.Format("2006-01-02 15:04"),
			snap.Description)
	}
	return w.Flush()
}

func (f *TableFormatter) FormatNetworkList(networks []domain.NetworkInfo) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "NAME\tACTIVE\tAUTOSTART\tFORWARD\tBRIDGE\tDOMAIN")
	fmt.Fprintln(w, "----\t------\t---------\t-------\t------\t------")

	for _, net := range networks {
		active := "no"
		if net.Active {
			active = "yes"
		}
		autostart := "no"
		if net.Autostart {
			autostart = "yes"
		}
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
			net.Name,
			active,
			autostart,
			net.Forward,
			net.Bridge,
			net.Domain)
	}
	return w.Flush()
}

func (f *TableFormatter) FormatConnectionList(connections []domain.ConnectionInfo) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "ID\tURI\tTYPE\tHOSTNAME\tCONNECTED")
	fmt.Fprintln(w, "--\t---\t----\t--------\t---------")

	for _, conn := range connections {
		connected := "no"
		if conn.Connected {
			connected = "yes"
		}
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
			conn.ID[:8],
			conn.URI,
			conn.Type,
			conn.Hostname,
			connected)
	}
	return w.Flush()
}

func (f *TableFormatter) FormatDHCPLeases(leases []domain.DHCPLease) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "IP ADDRESS\tMAC ADDRESS\tHOSTNAME\tEXPIRY")
	fmt.Fprintln(w, "----------\t-----------\t--------\t------")

	for _, lease := range leases {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
			lease.IPAddress,
			lease.MACAddress,
			lease.Hostname,
			lease.ExpiryTime.Format("2006-01-02 15:04"))
	}
	return w.Flush()
}

func (f *TableFormatter) FormatEventList(events []domain.Event) error {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	fmt.Fprintln(w, "TIME\tTYPE\tTARGET\tACTION\tDETAIL")
	fmt.Fprintln(w, "----\t----\t------\t------\t------")

	for _, evt := range events {
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
			evt.Timestamp.Format("15:04:05"),
			evt.Type,
			evt.Target,
			evt.Action,
			evt.Detail)
	}
	return w.Flush()
}

// JSONFormatter JSON格式输出
type JSONFormatter struct{}

func (f *JSONFormatter) FormatVMList(vms []domain.VMInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": vms})
}

func (f *JSONFormatter) FormatVMInfo(vm *domain.VMInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": vm})
}

func (f *JSONFormatter) FormatStoragePoolList(pools []domain.StoragePoolInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": pools})
}

func (f *JSONFormatter) FormatStorageVolumeList(volumes []domain.StorageVolumeInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": volumes})
}

func (f *JSONFormatter) FormatSnapshotList(snapshots []domain.SnapshotInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": snapshots})
}

func (f *JSONFormatter) FormatNetworkList(networks []domain.NetworkInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": networks})
}

func (f *JSONFormatter) FormatConnectionList(connections []domain.ConnectionInfo) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": connections})
}

func (f *JSONFormatter) FormatDHCPLeases(leases []domain.DHCPLease) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": leases})
}

func (f *JSONFormatter) FormatEventList(events []domain.Event) error {
	return json.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": events})
}

// YAMLFormatter YAML格式输出
type YAMLFormatter struct{}

func (f *YAMLFormatter) FormatVMList(vms []domain.VMInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": vms})
}

func (f *YAMLFormatter) FormatVMInfo(vm *domain.VMInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": vm})
}

func (f *YAMLFormatter) FormatStoragePoolList(pools []domain.StoragePoolInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": pools})
}

func (f *YAMLFormatter) FormatStorageVolumeList(volumes []domain.StorageVolumeInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": volumes})
}

func (f *YAMLFormatter) FormatSnapshotList(snapshots []domain.SnapshotInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": snapshots})
}

func (f *YAMLFormatter) FormatNetworkList(networks []domain.NetworkInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": networks})
}

func (f *YAMLFormatter) FormatConnectionList(connections []domain.ConnectionInfo) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": connections})
}

func (f *YAMLFormatter) FormatDHCPLeases(leases []domain.DHCPLease) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": leases})
}

func (f *YAMLFormatter) FormatEventList(events []domain.Event) error {
	return yaml.NewEncoder(os.Stdout).Encode(map[string]interface{}{"data": events})
}

// NewFormatter 根据格式创建格式化器
func NewFormatter(format OutputFormat) OutputFormatter {
	switch format {
	case FormatJSON:
		return &JSONFormatter{}
	case FormatYAML:
		return &YAMLFormatter{}
	default:
		return &TableFormatter{}
	}
}

// 辅助函数：字节格式化（从 storage.go 移过来以避免重复声明）
func formatBytes(bytes uint64) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}
	div, exp := uint64(unit), 0
	for n := bytes / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp])
}
